package com.googlecode.gaetwbot;

import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;

import twitter4j.DirectMessage;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;

import com.googlecode.gaetwbot.service.SettingService;

/**
 * Twitterの各種タイムラインを取得するサンプル。
 * <p>タイムラインの指定は{@literal tl}パラメータで指定する。<br />
 * 表示できるタイムラインの種類は以下の通り。</p>
 * <dl>
 * <dt>tlの指定なし</dt><dd>publicタイムライン</dd>
 * <dt>repliesまたはmentions</dt><dd>ログインユーザのmentions</dd>
 * <dt>direct</dt><dd>ログインユーザへのダイレクトメッセージ</dd>
 * <dt>friends</dt><dd>ログインユーザへのFriendsタイムライン</dd>
 * <dt>rtbyme</dt><dd>ログインユーザがRetweetしたつぶやき</dd>
 * <dt>rttome</dt><dd>ログインユーザのFriendsがRetweetしたつぶやき</dd>
 * <dt>rtofme</dt><dd>誰かにRetweetされた、ログインユーザのつぶやき</dd>
 * </dl>
 * <p>publicタイムライン以外のタイムラインが指定されている状態で、
 * データストアからログイン情報が取得できなかった場合はログイン情報を入力するためのFormを表示する。</p>
 * @author shin1ogawa
 */
@SuppressWarnings("serial")
public class TimelineServlet extends HttpServlet {

	static final Logger logger = Logger.getLogger(TimelineServlet.class.getName());


	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		String timeline = request.getParameter("tl");

		try {
			if (StringUtils.isEmpty(timeline)) {
				// public timelineを表示する。
				responseStatuses(response, "public timeline", new Twitter().getPublicTimeline());
				return;
			}

			// ここから先はログインが必要な機能へのアクセス。
			String twitterUser = SettingService.get("twitterUser");
			String twitterPassword = SettingService.get("twitterPassword");
			if (StringUtils.isEmpty(twitterUser) || StringUtils.isEmpty(twitterPassword)) {
				responseLoginForm(request, response);
				return;
			}
			Twitter twitter = new Twitter(twitterUser, twitterPassword);
			if (timeline.equals("replies") || timeline.equals("mentions")) {
				// ログインユーザに対するmentionsを表示する。
				responseStatuses(response, "mentions", twitter.getMentions());
			} else if (timeline.equals("direct")) {
				// ログインユーザに送られたDirectMessageを表示する。
				responseDirectMessages(response, "direct messages", twitter.getDirectMessages());
			} else if (timeline.equals("friends")) {
				// ログインユーザがRetweetしたTweetを表示する。
				responseStatuses(response, "Friends", twitter.getFriendsTimeline());
			} else if (timeline.equals("rtbyme")) {
				// ログインユーザがRetweetしたTweetを表示する。
				responseStatuses(response, "Retweeted By Me", twitter.getRetweetedByMe());
			} else if (timeline.equals("rttome")) {
				// ログインユーザのFriendsがRetweetしたTweetを表示する。
				responseStatuses(response, "Retweeted To Me", twitter.getRetweetedToMe());
			} else if (timeline.equals("rtofme")) {
				// ログインユーザがRetweetされたTweetを表示する。
				responseStatuses(response, "Retweets Of Me", twitter.getRetweetsOfMe());
			} else {
				responseError(response, "理解できないパラメータ。tl=" + timeline);
			}
		} catch (TwitterException e) {
			logger.log(Level.WARNING, "twitterとの通信でエラーが発生しました。", e);
			responseError(response, "twitterとの通信でエラーが発生しました。" + e.toString());
		}
	}

	private void responseStatuses(HttpServletResponse response, String timeline,
			List<Status> statuses) throws IOException {
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		VelocityContext context = new VelocityContext();
		context.put("timeline", timeline);
		context.put("statuses", statuses);
		VelocityUtil.merge(context, "/template/timeline.html", response);
		response.flushBuffer();
	}

	private void responseDirectMessages(HttpServletResponse response, String timeline,
			List<DirectMessage> statuses) throws IOException {
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		VelocityContext context = new VelocityContext();
		context.put("timeline", timeline);
		context.put("statuses", statuses);
		VelocityUtil.merge(context, "/template/directmessages.html", response);
		response.flushBuffer();
	}

	private void responseLoginForm(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		VelocityContext context = new VelocityContext();
		String redirectTo = request.getRequestURI();
		if (StringUtils.isNotEmpty(request.getQueryString())) {
			redirectTo += "?" + request.getQueryString();
		}
		context.put("redirectTo", redirectTo);
		VelocityUtil.merge(context, "/template/login.html", response);
		response.flushBuffer();
	}

	private void responseError(HttpServletResponse response, String message) throws IOException {
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		VelocityContext context = new VelocityContext();
		context.put("message", message);
		VelocityUtil.merge(context, "/template/error.html", response);
		response.flushBuffer();
	}
}
